﻿using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
using System.Drawing;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace DirectX_CS
{
    public class LightCone : IColorable, IDisposable
    {
		bool mVisible = true;
		[PGBrowsable]
		public bool Visible
		{
			get { return mVisible; }
			set
			{
				mVisible = value;
				if (coneTop!= null)
					coneTop.EnableCallRenderPrimitives = value;
				if (coneBottom != null)
					coneBottom.EnableCallRenderPrimitives = value;
			}
		}
		public Light GetLight()
		{
			return MainProgram.DxDevice.Lights[mLightNumber];
		}
		public void Recreate()
		{
			Light l = GetLight();
			MainVertexColor = l.Ambient;
			Visible = l.Enabled; //for now until have an option to turn off light cones

			if (coneTop != null)
			{
				coneTop.StartCenterPoint = l.Position;
				coneTop.Recreate();
			}

			if (coneBottom != null)
				coneBottom.Recreate();
		
		}
		[PGBrowsable]
        TriangleFan coneTop = null;
		[PGBrowsable]
		TriangleFan coneBottom = null;

        private int mDivisions = 10;
		[PGBrowsable]
		public int Divisions
        {
            get { return mDivisions; }
            set { mDivisions = value;
				if (coneTop != null)
					coneTop.AngleIterations = value;
				if (coneBottom!=null)
					coneBottom.AngleIterations = value;
            }
        }

        protected float mHeight = 10;
		[PGBrowsable]
		public float Height
        {
            get { return mHeight; }
            set { 
                mHeight = value;
            }
        }

		int mLightNumber = -1;
		[PGBrowsable]
		public int LightNumber
		{
			get { return mLightNumber; }
			set { mLightNumber = value; }
		}

		public Vector3 ConeTopRadialVFunc(float a)
		{
			Light l = GetLight();
			double rng = l.Range;
			double h = 10; //float h = Height;
			Vector3 lp = l.Position;
			Vector3 d = l.Direction;
			Vector3 nd = d; nd.Normalize();//in other words nd = normal(d)
			//float dlen = d.Length();
			double x, y, z;
			//float tan theta =  radius /hypotenuse 
			//well i have theta i have the adjacent side but we need the radius or opposite side
			//so we need to use tan l.outerconeangle = o / a or  just tan = radius / height so then 
			// solving for radius we get radius = tan * h 
			double Radius = Math.Tan(l.OuterConeAngle) * h;
			x = Math.Cos(a) * Radius; //(float)(Math.Cos(l.OuterConeAngle) *  h * Math.Cos(a) );
			y = Math.Sin(a) * Radius; //(float)(Math.Sin(l.OuterConeAngle) *  h * Math.Sin(a));
			if (d.Z >= 0)
				z = h;
			else
				z = -h;
			

			//circle.. centered at vtip an perpendicular to direction
			//have theta, have rnd, have the normal need the xyz 
			Vector3 tipPosLocal = nd; tipPosLocal.Scale((float)h);//new Vector3((float)(nd.X * h), (float)(nd.Y * h), (float)(nd.Z * h));

			Vector3 from = new Vector3(0,0,0);
			Vector3 to = tipPosLocal; //try nd
			Vector3 up = new Vector3(0, 0, 1);
			Matrix lookAt = Matrix.LookAtRH(from, to, up);
			//Matrix inv = lookAt; inv.Invert();	 

			Vector3 pos = new Vector3((float)x, (float)y, (float)z);
			Vector3 rotPos = pos;

			if (nd.X == 0 && nd.Y == 0)
			{
				//rotPos = pos;
			}
			else
			{
				rotPos.TransformCoordinate(lookAt); //try lookAt//
			}
			
			Vector3 tranPos = tipPosLocal + rotPos + lp;//try pos + lp;///try 
			
			return tranPos;

			//return pos + lp; //try just creating a nice upside down cone first

			//double h = Math.Cos(l.OuterConeAngle) * l.Range;
			//double h = Height ;

			//Vector3 beforeRotation = new Vector3((float)x / dlen, (float)y / dlen, (float)z/ dlen);

			//Matrix rotX = Matrix.RotationX(d.X * NinetyDegreesR);
			//Matrix rotY = Matrix.RotationY(d.Y * NinetyDegreesR);
			//Matrix rotZ = Matrix.RotationZ(d.Z * NinetyDegreesR);
			//Matrix prod = rotX * rotY * rotZ;
			//Vector3 dirRotation = new Vector3((float)Math.Cos(d.X) / dlen, (float)Math.Cos(d.Y) / dlen, (float)Math.Cos(d.Z) / dlen);

			//Vector3 afterRotation = new Vector3(dirRotation.X * beforeRotation.X, dirRotation.Y * beforeRotation.Y, dirRotation.Z * beforeRotation.Z) ;

			//double radius = Math.Sin(l.OuterConeAngle) * h;
			//Vector3 beforeRotation = new Vector3((float)x, (float)y, (float)z);
			//float NinetyDegreesR = (float)Math.PI / 4;
			//Matrix dirRotMat = Matrix.RotationX(d.X / dlen) *
			//Matrix.RotationY(d.Y / dlen);
			//Vector3 afterRotation = beforeRotation; afterRotation.TransformCoordinate(dirRotMat);
			//Vector3 result = (afterRotation + lp); result.TransformCoordinate(Matrix.RotationZ(d.Z));
			//return result;

			//Vector3 theOuterPos = new Vector3((float)x,(float)y,(float)z);
			//return lp + theOuterPos;//


		}

		public LightCone(int lightNumber)
		{
			mLightNumber = lightNumber;
			//create the cone top : needs changing
			//coneBottom = new TriangleFan(XFunc, YFunc, ZFunc, new Vector3(0, 0, 0), 0, 2f * (float)Math.PI, mDivisions);  
			//creat the circle
			coneTop = new TriangleFan(this.ConeTopRadialVFunc, MainProgram.DxDevice.Lights[lightNumber].Position, false);
		}
		Color mainVertexColor = Color.White;
		[PGBrowsable]
		public Color MainVertexColor
		{
			get { return mainVertexColor; }
			set {
				mainVertexColor = value;
				if (coneTop!= null)
					coneTop.MainVertexColor = value;
				if (coneBottom!=null)
				coneBottom.MainVertexColor = value;
			
			}
		}

        ~LightCone()
        {
			DisposeInstance();
        }

		public void DisposeInstance()
		{
			if (coneTop != null)
			{
				coneTop.UnRegister(); coneTop = null;
			}
			if (coneBottom != null)
			{
				coneBottom.UnRegister(); coneBottom = null;
			}
		}

    }
}
